// lib/handlebars/base.js
var Handlebars = {};

Handlebars.VERSION = "1.0.beta.6";

Handlebars.helpers = {};
Handlebars.partials = {};

Handlebars.registerHelper = function (name, fn, inverse) {
    if (inverse) {
        fn.not = inverse;
    }
    this.helpers[name] = fn;
};

Handlebars.registerPartial = function (name, str) {
    this.partials[name] = str;
};

Handlebars.registerHelper('helperMissing', function (arg) {
    if (arguments.length === 2) {
        return undefined;
    } else {
        throw new Error("Could not find property '" + arg + "'");
    }
});

var toString = Object.prototype.toString, functionType = "[object Function]";

Handlebars.registerHelper('blockHelperMissing', function (context, options) {
    var inverse = options.inverse || function () {
    }, fn = options.fn;


    var ret = "";
    var type = toString.call(context);

    if (type === functionType) {
        context = context.call(this);
    }

    if (context === true) {
        return fn(this);
    } else if (context === false || context == null) {
        return inverse(this);
    } else if (type === "[object Array]") {
        if (context.length > 0) {
            for (var i = 0, j = context.length; i < j; i++) {
                ret = ret + fn(context[i]);
            }
        } else {
            ret = inverse(this);
        }
        return ret;
    } else {
        return fn(context);
    }
});

Handlebars.registerHelper('each', function (context, options) {
    var fn = options.fn, inverse = options.inverse;
    var ret = "";

    if (context && context.length > 0) {
        for (var i = 0, j = context.length; i < j; i++) {
            ret = ret + fn(context[i]);
        }
    } else {
        ret = inverse(this);
    }
    return ret;
});

Handlebars.registerHelper('if', function (context, options) {
    var type = toString.call(context);
    if (type === functionType) {
        context = context.call(this);
    }

    if (!context || Handlebars.Utils.isEmpty(context)) {
        return options.inverse(this);
    } else {
        return options.fn(this);
    }
});

Handlebars.registerHelper('unless', function (context, options) {
    var fn = options.fn, inverse = options.inverse;
    options.fn = inverse;
    options.inverse = fn;

    return Handlebars.helpers['if'].call(this, context, options);
});

Handlebars.registerHelper('with', function (context, options) {
    return options.fn(context);
});

Handlebars.registerHelper('log', function (context) {
    Handlebars.log(context);
});
;
// lib/handlebars/compiler/parser.js
/* Jison generated parser */
var handlebars = (function () {

    var parser = {trace:function trace() {
    },
        yy:{},
        symbols_:{"error":2, "root":3, "program":4, "EOF":5, "statements":6, "simpleInverse":7, "statement":8, "openInverse":9, "closeBlock":10, "openBlock":11, "mustache":12, "partial":13, "CONTENT":14, "COMMENT":15, "OPEN_BLOCK":16, "inMustache":17, "CLOSE":18, "OPEN_INVERSE":19, "OPEN_ENDBLOCK":20, "path":21, "OPEN":22, "OPEN_UNESCAPED":23, "OPEN_PARTIAL":24, "params":25, "hash":26, "param":27, "STRING":28, "INTEGER":29, "BOOLEAN":30, "hashSegments":31, "hashSegment":32, "ID":33, "EQUALS":34, "pathSegments":35, "SEP":36, "$accept":0, "$end":1},
        terminals_:{2:"error", 5:"EOF", 14:"CONTENT", 15:"COMMENT", 16:"OPEN_BLOCK", 18:"CLOSE", 19:"OPEN_INVERSE", 20:"OPEN_ENDBLOCK", 22:"OPEN", 23:"OPEN_UNESCAPED", 24:"OPEN_PARTIAL", 28:"STRING", 29:"INTEGER", 30:"BOOLEAN", 33:"ID", 34:"EQUALS", 36:"SEP"},
        productions_:[0, [3, 2], [4, 3], [4, 1], [4, 0], [6, 1], [6, 2], [8, 3], [8, 3], [8, 1], [8, 1], [8, 1], [8, 1], [11, 3], [9, 3], [10, 3], [12, 3], [12, 3], [13, 3], [13, 4], [7, 2], [17, 3], [17, 2], [17, 2], [17, 1], [25, 2], [25, 1], [27, 1], [27, 1], [27, 1], [27, 1], [26, 1], [31, 2], [31, 1], [32, 3], [32, 3], [32, 3], [32, 3], [21, 1], [35, 3], [35, 1]],
        performAction:function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {

            var $0 = $$.length - 1;
            switch (yystate) {
                case 1:
                    return $$[$0 - 1]
                    break;
                case 2:
                    this.$ = new yy.ProgramNode($$[$0 - 2], $$[$0])
                    break;
                case 3:
                    this.$ = new yy.ProgramNode($$[$0])
                    break;
                case 4:
                    this.$ = new yy.ProgramNode([])
                    break;
                case 5:
                    this.$ = [$$[$0]]
                    break;
                case 6:
                    $$[$0 - 1].push($$[$0]);
                    this.$ = $$[$0 - 1]
                    break;
                case 7:
                    this.$ = new yy.InverseNode($$[$0 - 2], $$[$0 - 1], $$[$0])
                    break;
                case 8:
                    this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1], $$[$0])
                    break;
                case 9:
                    this.$ = $$[$0]
                    break;
                case 10:
                    this.$ = $$[$0]
                    break;
                case 11:
                    this.$ = new yy.ContentNode($$[$0])
                    break;
                case 12:
                    this.$ = new yy.CommentNode($$[$0])
                    break;
                case 13:
                    this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1])
                    break;
                case 14:
                    this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1])
                    break;
                case 15:
                    this.$ = $$[$0 - 1]
                    break;
                case 16:
                    this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1])
                    break;
                case 17:
                    this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1], true)
                    break;
                case 18:
                    this.$ = new yy.PartialNode($$[$0 - 1])
                    break;
                case 19:
                    this.$ = new yy.PartialNode($$[$0 - 2], $$[$0 - 1])
                    break;
                case 20:
                    break;
                case 21:
                    this.$ = [[$$[$0 - 2]].concat($$[$0 - 1]), $$[$0]]
                    break;
                case 22:
                    this.$ = [[$$[$0 - 1]].concat($$[$0]), null]
                    break;
                case 23:
                    this.$ = [
                        [$$[$0 - 1]],
                        $$[$0]
                    ]
                    break;
                case 24:
                    this.$ = [
                        [$$[$0]],
                        null
                    ]
                    break;
                case 25:
                    $$[$0 - 1].push($$[$0]);
                    this.$ = $$[$0 - 1];
                    break;
                case 26:
                    this.$ = [$$[$0]]
                    break;
                case 27:
                    this.$ = $$[$0]
                    break;
                case 28:
                    this.$ = new yy.StringNode($$[$0])
                    break;
                case 29:
                    this.$ = new yy.IntegerNode($$[$0])
                    break;
                case 30:
                    this.$ = new yy.BooleanNode($$[$0])
                    break;
                case 31:
                    this.$ = new yy.HashNode($$[$0])
                    break;
                case 32:
                    $$[$0 - 1].push($$[$0]);
                    this.$ = $$[$0 - 1]
                    break;
                case 33:
                    this.$ = [$$[$0]]
                    break;
                case 34:
                    this.$ = [$$[$0 - 2], $$[$0]]
                    break;
                case 35:
                    this.$ = [$$[$0 - 2], new yy.StringNode($$[$0])]
                    break;
                case 36:
                    this.$ = [$$[$0 - 2], new yy.IntegerNode($$[$0])]
                    break;
                case 37:
                    this.$ = [$$[$0 - 2], new yy.BooleanNode($$[$0])]
                    break;
                case 38:
                    this.$ = new yy.IdNode($$[$0])
                    break;
                case 39:
                    $$[$0 - 2].push($$[$0]);
                    this.$ = $$[$0 - 2];
                    break;
                case 40:
                    this.$ = [$$[$0]]
                    break;
            }
        },
        table:[
            {3:1, 4:2, 5:[2, 4], 6:3, 8:4, 9:5, 11:6, 12:7, 13:8, 14:[1, 9], 15:[1, 10], 16:[1, 12], 19:[1, 11], 22:[1, 13], 23:[1, 14], 24:[1, 15]},
            {1:[3]},
            {5:[1, 16]},
            {5:[2, 3], 7:17, 8:18, 9:5, 11:6, 12:7, 13:8, 14:[1, 9], 15:[1, 10], 16:[1, 12], 19:[1, 19], 20:[2, 3], 22:[1, 13], 23:[1, 14], 24:[1, 15]},
            {5:[2, 5], 14:[2, 5], 15:[2, 5], 16:[2, 5], 19:[2, 5], 20:[2, 5], 22:[2, 5], 23:[2, 5], 24:[2, 5]},
            {4:20, 6:3, 8:4, 9:5, 11:6, 12:7, 13:8, 14:[1, 9], 15:[1, 10], 16:[1, 12], 19:[1, 11], 20:[2, 4], 22:[1, 13], 23:[1, 14], 24:[1, 15]},
            {4:21, 6:3, 8:4, 9:5, 11:6, 12:7, 13:8, 14:[1, 9], 15:[1, 10], 16:[1, 12], 19:[1, 11], 20:[2, 4], 22:[1, 13], 23:[1, 14], 24:[1, 15]},
            {5:[2, 9], 14:[2, 9], 15:[2, 9], 16:[2, 9], 19:[2, 9], 20:[2, 9], 22:[2, 9], 23:[2, 9], 24:[2, 9]},
            {5:[2, 10], 14:[2, 10], 15:[2, 10], 16:[2, 10], 19:[2, 10], 20:[2, 10], 22:[2, 10], 23:[2, 10], 24:[2, 10]},
            {5:[2, 11], 14:[2, 11], 15:[2, 11], 16:[2, 11], 19:[2, 11], 20:[2, 11], 22:[2, 11], 23:[2, 11], 24:[2, 11]},
            {5:[2, 12], 14:[2, 12], 15:[2, 12], 16:[2, 12], 19:[2, 12], 20:[2, 12], 22:[2, 12], 23:[2, 12], 24:[2, 12]},
            {17:22, 21:23, 33:[1, 25], 35:24},
            {17:26, 21:23, 33:[1, 25], 35:24},
            {17:27, 21:23, 33:[1, 25], 35:24},
            {17:28, 21:23, 33:[1, 25], 35:24},
            {21:29, 33:[1, 25], 35:24},
            {1:[2, 1]},
            {6:30, 8:4, 9:5, 11:6, 12:7, 13:8, 14:[1, 9], 15:[1, 10], 16:[1, 12], 19:[1, 11], 22:[1, 13], 23:[1, 14], 24:[1, 15]},
            {5:[2, 6], 14:[2, 6], 15:[2, 6], 16:[2, 6], 19:[2, 6], 20:[2, 6], 22:[2, 6], 23:[2, 6], 24:[2, 6]},
            {17:22, 18:[1, 31], 21:23, 33:[1, 25], 35:24},
            {10:32, 20:[1, 33]},
            {10:34, 20:[1, 33]},
            {18:[1, 35]},
            {18:[2, 24], 21:40, 25:36, 26:37, 27:38, 28:[1, 41], 29:[1, 42], 30:[1, 43], 31:39, 32:44, 33:[1, 45], 35:24},
            {18:[2, 38], 28:[2, 38], 29:[2, 38], 30:[2, 38], 33:[2, 38], 36:[1, 46]},
            {18:[2, 40], 28:[2, 40], 29:[2, 40], 30:[2, 40], 33:[2, 40], 36:[2, 40]},
            {18:[1, 47]},
            {18:[1, 48]},
            {18:[1, 49]},
            {18:[1, 50], 21:51, 33:[1, 25], 35:24},
            {5:[2, 2], 8:18, 9:5, 11:6, 12:7, 13:8, 14:[1, 9], 15:[1, 10], 16:[1, 12], 19:[1, 11], 20:[2, 2], 22:[1, 13], 23:[1, 14], 24:[1, 15]},
            {14:[2, 20], 15:[2, 20], 16:[2, 20], 19:[2, 20], 22:[2, 20], 23:[2, 20], 24:[2, 20]},
            {5:[2, 7], 14:[2, 7], 15:[2, 7], 16:[2, 7], 19:[2, 7], 20:[2, 7], 22:[2, 7], 23:[2, 7], 24:[2, 7]},
            {21:52, 33:[1, 25], 35:24},
            {5:[2, 8], 14:[2, 8], 15:[2, 8], 16:[2, 8], 19:[2, 8], 20:[2, 8], 22:[2, 8], 23:[2, 8], 24:[2, 8]},
            {14:[2, 14], 15:[2, 14], 16:[2, 14], 19:[2, 14], 20:[2, 14], 22:[2, 14], 23:[2, 14], 24:[2, 14]},
            {18:[2, 22], 21:40, 26:53, 27:54, 28:[1, 41], 29:[1, 42], 30:[1, 43], 31:39, 32:44, 33:[1, 45], 35:24},
            {18:[2, 23]},
            {18:[2, 26], 28:[2, 26], 29:[2, 26], 30:[2, 26], 33:[2, 26]},
            {18:[2, 31], 32:55, 33:[1, 56]},
            {18:[2, 27], 28:[2, 27], 29:[2, 27], 30:[2, 27], 33:[2, 27]},
            {18:[2, 28], 28:[2, 28], 29:[2, 28], 30:[2, 28], 33:[2, 28]},
            {18:[2, 29], 28:[2, 29], 29:[2, 29], 30:[2, 29], 33:[2, 29]},
            {18:[2, 30], 28:[2, 30], 29:[2, 30], 30:[2, 30], 33:[2, 30]},
            {18:[2, 33], 33:[2, 33]},
            {18:[2, 40], 28:[2, 40], 29:[2, 40], 30:[2, 40], 33:[2, 40], 34:[1, 57], 36:[2, 40]},
            {33:[1, 58]},
            {14:[2, 13], 15:[2, 13], 16:[2, 13], 19:[2, 13], 20:[2, 13], 22:[2, 13], 23:[2, 13], 24:[2, 13]},
            {5:[2, 16], 14:[2, 16], 15:[2, 16], 16:[2, 16], 19:[2, 16], 20:[2, 16], 22:[2, 16], 23:[2, 16], 24:[2, 16]},
            {5:[2, 17], 14:[2, 17], 15:[2, 17], 16:[2, 17], 19:[2, 17], 20:[2, 17], 22:[2, 17], 23:[2, 17], 24:[2, 17]},
            {5:[2, 18], 14:[2, 18], 15:[2, 18], 16:[2, 18], 19:[2, 18], 20:[2, 18], 22:[2, 18], 23:[2, 18], 24:[2, 18]},
            {18:[1, 59]},
            {18:[1, 60]},
            {18:[2, 21]},
            {18:[2, 25], 28:[2, 25], 29:[2, 25], 30:[2, 25], 33:[2, 25]},
            {18:[2, 32], 33:[2, 32]},
            {34:[1, 57]},
            {21:61, 28:[1, 62], 29:[1, 63], 30:[1, 64], 33:[1, 25], 35:24},
            {18:[2, 39], 28:[2, 39], 29:[2, 39], 30:[2, 39], 33:[2, 39], 36:[2, 39]},
            {5:[2, 19], 14:[2, 19], 15:[2, 19], 16:[2, 19], 19:[2, 19], 20:[2, 19], 22:[2, 19], 23:[2, 19], 24:[2, 19]},
            {5:[2, 15], 14:[2, 15], 15:[2, 15], 16:[2, 15], 19:[2, 15], 20:[2, 15], 22:[2, 15], 23:[2, 15], 24:[2, 15]},
            {18:[2, 34], 33:[2, 34]},
            {18:[2, 35], 33:[2, 35]},
            {18:[2, 36], 33:[2, 36]},
            {18:[2, 37], 33:[2, 37]}
        ],
        defaultActions:{16:[2, 1], 37:[2, 23], 53:[2, 21]},
        parseError:function parseError(str, hash) {
            throw new Error(str);
        },
        parse:function parse(input) {
            var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
            this.lexer.setInput(input);
            this.lexer.yy = this.yy;
            this.yy.lexer = this.lexer;
            if (typeof this.lexer.yylloc == "undefined")
                this.lexer.yylloc = {};
            var yyloc = this.lexer.yylloc;
            lstack.push(yyloc);
            if (typeof this.yy.parseError === "function")
                this.parseError = this.yy.parseError;
            function popStack(n) {
                stack.length = stack.length - 2 * n;
                vstack.length = vstack.length - n;
                lstack.length = lstack.length - n;
            }

            function lex() {
                var token;
                token = self.lexer.lex() || 1;
                if (typeof token !== "number") {
                    token = self.symbols_[token] || token;
                }
                return token;
            }

            var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
            while (true) {
                state = stack[stack.length - 1];
                if (this.defaultActions[state]) {
                    action = this.defaultActions[state];
                } else {
                    if (symbol == null)
                        symbol = lex();
                    action = table[state] && table[state][symbol];
                }
                if (typeof action === "undefined" || !action.length || !action[0]) {
                    if (!recovering) {
                        expected = [];
                        for (p in table[state])
                            if (this.terminals_[p] && p > 2) {
                                expected.push("'" + this.terminals_[p] + "'");
                            }
                        var errStr = "";
                        if (this.lexer.showPosition) {
                            errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'";
                        } else {
                            errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
                        }
                        this.parseError(errStr, {text:this.lexer.match, token:this.terminals_[symbol] || symbol, line:this.lexer.yylineno, loc:yyloc, expected:expected});
                    }
                }
                if (action[0] instanceof Array && action.length > 1) {
                    throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
                }
                switch (action[0]) {
                    case 1:
                        stack.push(symbol);
                        vstack.push(this.lexer.yytext);
                        lstack.push(this.lexer.yylloc);
                        stack.push(action[1]);
                        symbol = null;
                        if (!preErrorSymbol) {
                            yyleng = this.lexer.yyleng;
                            yytext = this.lexer.yytext;
                            yylineno = this.lexer.yylineno;
                            yyloc = this.lexer.yylloc;
                            if (recovering > 0)
                                recovering--;
                        } else {
                            symbol = preErrorSymbol;
                            preErrorSymbol = null;
                        }
                        break;
                    case 2:
                        len = this.productions_[action[1]][1];
                        yyval.$ = vstack[vstack.length - len];
                        yyval._$ = {first_line:lstack[lstack.length - (len || 1)].first_line, last_line:lstack[lstack.length - 1].last_line, first_column:lstack[lstack.length - (len || 1)].first_column, last_column:lstack[lstack.length - 1].last_column};
                        r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
                        if (typeof r !== "undefined") {
                            return r;
                        }
                        if (len) {
                            stack = stack.slice(0, -1 * len * 2);
                            vstack = vstack.slice(0, -1 * len);
                            lstack = lstack.slice(0, -1 * len);
                        }
                        stack.push(this.productions_[action[1]][0]);
                        vstack.push(yyval.$);
                        lstack.push(yyval._$);
                        newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
                        stack.push(newState);
                        break;
                    case 3:
                        return true;
                }
            }
            return true;
        }
    };
    /* Jison generated lexer */
    var lexer = (function () {

        var lexer = ({EOF:1,
            parseError:function parseError(str, hash) {
                if (this.yy.parseError) {
                    this.yy.parseError(str, hash);
                } else {
                    throw new Error(str);
                }
            },
            setInput:function (input) {
                this._input = input;
                this._more = this._less = this.done = false;
                this.yylineno = this.yyleng = 0;
                this.yytext = this.matched = this.match = '';
                this.conditionStack = ['INITIAL'];
                this.yylloc = {first_line:1, first_column:0, last_line:1, last_column:0};
                return this;
            },
            input:function () {
                var ch = this._input[0];
                this.yytext += ch;
                this.yyleng++;
                this.match += ch;
                this.matched += ch;
                var lines = ch.match(/\n/);
                if (lines) this.yylineno++;
                this._input = this._input.slice(1);
                return ch;
            },
            unput:function (ch) {
                this._input = ch + this._input;
                return this;
            },
            more:function () {
                this._more = true;
                return this;
            },
            pastInput:function () {
                var past = this.matched.substr(0, this.matched.length - this.match.length);
                return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, "");
            },
            upcomingInput:function () {
                var next = this.match;
                if (next.length < 20) {
                    next += this._input.substr(0, 20 - next.length);
                }
                return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
            },
            showPosition:function () {
                var pre = this.pastInput();
                var c = new Array(pre.length + 1).join("-");
                return pre + this.upcomingInput() + "\n" + c + "^";
            },
            next:function () {
                if (this.done) {
                    return this.EOF;
                }
                if (!this._input) this.done = true;

                var token,
                    match,
                    col,
                    lines;
                if (!this._more) {
                    this.yytext = '';
                    this.match = '';
                }
                var rules = this._currentRules();
                for (var i = 0; i < rules.length; i++) {
                    match = this._input.match(this.rules[rules[i]]);
                    if (match) {
                        lines = match[0].match(/\n.*/g);
                        if (lines) this.yylineno += lines.length;
                        this.yylloc = {first_line:this.yylloc.last_line,
                            last_line:this.yylineno + 1,
                            first_column:this.yylloc.last_column,
                            last_column:lines ? lines[lines.length - 1].length - 1 : this.yylloc.last_column + match[0].length}
                        this.yytext += match[0];
                        this.match += match[0];
                        this.matches = match;
                        this.yyleng = this.yytext.length;
                        this._more = false;
                        this._input = this._input.slice(match[0].length);
                        this.matched += match[0];
                        token = this.performAction.call(this, this.yy, this, rules[i], this.conditionStack[this.conditionStack.length - 1]);
                        if (token) return token;
                        else return;
                    }
                }
                if (this._input === "") {
                    return this.EOF;
                } else {
                    this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(),
                        {text:"", token:null, line:this.yylineno});
                }
            },
            lex:function lex() {
                var r = this.next();
                if (typeof r !== 'undefined') {
                    return r;
                } else {
                    return this.lex();
                }
            },
            begin:function begin(condition) {
                this.conditionStack.push(condition);
            },
            popState:function popState() {
                return this.conditionStack.pop();
            },
            _currentRules:function _currentRules() {
                return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
            },
            topState:function () {
                return this.conditionStack[this.conditionStack.length - 2];
            },
            pushState:function begin(condition) {
                this.begin(condition);
            }});
        lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {

            var YYSTATE = YY_START
            switch ($avoiding_name_collisions) {
                case 0:
                    if (yy_.yytext.slice(-1) !== "\\") this.begin("mu");
                    if (yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1), this.begin("emu");
                    if (yy_.yytext) return 14;

                    break;
                case 1:
                    return 14;
                    break;
                case 2:
                    this.popState();
                    return 14;
                    break;
                case 3:
                    return 24;
                    break;
                case 4:
                    return 16;
                    break;
                case 5:
                    return 20;
                    break;
                case 6:
                    return 19;
                    break;
                case 7:
                    return 19;
                    break;
                case 8:
                    return 23;
                    break;
                case 9:
                    return 23;
                    break;
                case 10:
                    yy_.yytext = yy_.yytext.substr(3, yy_.yyleng - 5);
                    this.popState();
                    return 15;
                    break;
                case 11:
                    return 22;
                    break;
                case 12:
                    return 34;
                    break;
                case 13:
                    return 33;
                    break;
                case 14:
                    return 33;
                    break;
                case 15:
                    return 36;
                    break;
                case 16: /*ignore whitespace*/
                    break;
                case 17:
                    this.popState();
                    return 18;
                    break;
                case 18:
                    this.popState();
                    return 18;
                    break;
                case 19:
                    yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2).replace(/\\"/g, '"');
                    return 28;
                    break;
                case 20:
                    return 30;
                    break;
                case 21:
                    return 30;
                    break;
                case 22:
                    return 29;
                    break;
                case 23:
                    return 33;
                    break;
                case 24:
                    yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);
                    return 33;
                    break;
                case 25:
                    return 'INVALID';
                    break;
                case 26:
                    return 5;
                    break;
            }
        };
        lexer.rules = [/^[^\x00]*?(?=(\{\{))/, /^[^\x00]+/, /^[^\x00]{2,}?(?=(\{\{))/, /^\{\{>/, /^\{\{#/, /^\{\{\//, /^\{\{\^/, /^\{\{\s*else\b/, /^\{\{\{/, /^\{\{&/, /^\{\{![\s\S]*?\}\}/, /^\{\{/, /^=/, /^\.(?=[} ])/, /^\.\./, /^[\/.]/, /^\s+/, /^\}\}\}/, /^\}\}/, /^"(\\["]|[^"])*"/, /^true(?=[}\s])/, /^false(?=[}\s])/, /^[0-9]+(?=[}\s])/, /^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/, /^\[[^\]]*\]/, /^./, /^$/];
        lexer.conditions = {"mu":{"rules":[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26], "inclusive":false}, "emu":{"rules":[2], "inclusive":false}, "INITIAL":{"rules":[0, 1, 26], "inclusive":true}};
        return lexer;
    })()
    parser.lexer = lexer;
    return parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
    exports.parser = handlebars;
    exports.parse = function () {
        return handlebars.parse.apply(handlebars, arguments);
    }
    exports.main = function commonjsMain(args) {
        if (!args[1])
            throw new Error('Usage: ' + args[0] + ' FILE');
        if (typeof process !== 'undefined') {
            var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
        } else {
            var cwd = require("file").path(require("file").cwd());
            var source = cwd.join(args[1]).read({charset:"utf-8"});
        }
        return exports.parser.parse(source);
    }
    if (typeof module !== 'undefined' && require.main === module) {
        exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
    }
}
;
;
// lib/handlebars/compiler/base.js
Handlebars.Parser = handlebars;

Handlebars.parse = function (string) {
    Handlebars.Parser.yy = Handlebars.AST;
    return Handlebars.Parser.parse(string);
};

Handlebars.print = function (ast) {
    return new Handlebars.PrintVisitor().accept(ast);
};

Handlebars.logger = {
    DEBUG:0, INFO:1, WARN:2, ERROR:3, level:3,

    // override in the host environment
    log:function (level, str) {
    }
};

Handlebars.log = function (level, str) {
    Handlebars.logger.log(level, str);
};
;
// lib/handlebars/compiler/ast.js
(function () {

    Handlebars.AST = {};

    Handlebars.AST.ProgramNode = function (statements, inverse) {
        this.type = "program";
        this.statements = statements;
        if (inverse) {
            this.inverse = new Handlebars.AST.ProgramNode(inverse);
        }
    };

    Handlebars.AST.MustacheNode = function (params, hash, unescaped) {
        this.type = "mustache";
        this.id = params[0];
        this.params = params.slice(1);
        this.hash = hash;
        this.escaped = !unescaped;
    };

    Handlebars.AST.PartialNode = function (id, context) {
        this.type = "partial";

        // TODO: disallow complex IDs

        this.id = id;
        this.context = context;
    };

    var verifyMatch = function (open, close) {
        if (open.original !== close.original) {
            throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
        }
    };

    Handlebars.AST.BlockNode = function (mustache, program, close) {
        verifyMatch(mustache.id, close);
        this.type = "block";
        this.mustache = mustache;
        this.program = program;
    };

    Handlebars.AST.InverseNode = function (mustache, program, close) {
        verifyMatch(mustache.id, close);
        this.type = "inverse";
        this.mustache = mustache;
        this.program = program;
    };

    Handlebars.AST.ContentNode = function (string) {
        this.type = "content";
        this.string = string;
    };

    Handlebars.AST.HashNode = function (pairs) {
        this.type = "hash";
        this.pairs = pairs;
    };

    Handlebars.AST.IdNode = function (parts) {
        this.type = "ID";
        this.original = parts.join(".");

        var dig = [], depth = 0;

        for (var i = 0, l = parts.length; i < l; i++) {
            var part = parts[i];

            if (part === "..") {
                depth++;
            }
            else if (part === "." || part === "this") {
                this.isScoped = true;
            }
            else {
                dig.push(part);
            }
        }

        this.parts = dig;
        this.string = dig.join('.');
        this.depth = depth;
        this.isSimple = (dig.length === 1) && (depth === 0);
    };

    Handlebars.AST.StringNode = function (string) {
        this.type = "STRING";
        this.string = string;
    };

    Handlebars.AST.IntegerNode = function (integer) {
        this.type = "INTEGER";
        this.integer = integer;
    };

    Handlebars.AST.BooleanNode = function (bool) {
        this.type = "BOOLEAN";
        this.bool = bool;
    };

    Handlebars.AST.CommentNode = function (comment) {
        this.type = "comment";
        this.comment = comment;
    };

})();
;
// lib/handlebars/utils.js
Handlebars.Exception = function (message) {
    var tmp = Error.prototype.constructor.apply(this, arguments);

    for (var p in tmp) {
        if (tmp.hasOwnProperty(p)) {
            this[p] = tmp[p];
        }
    }

    this.message = tmp.message;
};
Handlebars.Exception.prototype = new Error;

// Build out our basic SafeString type
Handlebars.SafeString = function (string) {
    this.string = string;
};
Handlebars.SafeString.prototype.toString = function () {
    return this.string.toString();
};

(function () {
    var escape = {
        "<":"&lt;",
        ">":"&gt;",
        '"':"&quot;",
        "'":"&#x27;",
        "`":"&#x60;"
    };

    var badChars = /&(?!\w+;)|[<>"'`]/g;
    var possible = /[&<>"'`]/;

    var escapeChar = function (chr) {
        return escape[chr] || "&amp;";
    };

    Handlebars.Utils = {
        escapeExpression:function (string) {
            // don't escape SafeStrings, since they're already safe
            if (string instanceof Handlebars.SafeString) {
                return string.toString();
            } else if (string == null || string === false) {
                return "";
            }

            if (!possible.test(string)) {
                return string;
            }
            return string.replace(badChars, escapeChar);
        },

        isEmpty:function (value) {
            if (typeof value === "undefined") {
                return true;
            } else if (value === null) {
                return true;
            } else if (value === false) {
                return true;
            } else if (Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
                return true;
            } else {
                return false;
            }
        }
    };
})();
;
// lib/handlebars/compiler/compiler.js
Handlebars.Compiler = function () {
};
Handlebars.JavaScriptCompiler = function () {
};

(function (Compiler, JavaScriptCompiler) {
    Compiler.OPCODE_MAP = {
        appendContent:1,
        getContext:2,
        lookupWithHelpers:3,
        lookup:4,
        append:5,
        invokeMustache:6,
        appendEscaped:7,
        pushString:8,
        truthyOrFallback:9,
        functionOrFallback:10,
        invokeProgram:11,
        invokePartial:12,
        push:13,
        assignToHash:15,
        pushStringParam:16
    };

    Compiler.MULTI_PARAM_OPCODES = {
        appendContent:1,
        getContext:1,
        lookupWithHelpers:2,
        lookup:1,
        invokeMustache:3,
        pushString:1,
        truthyOrFallback:1,
        functionOrFallback:1,
        invokeProgram:3,
        invokePartial:1,
        push:1,
        assignToHash:1,
        pushStringParam:1
    };

    Compiler.DISASSEMBLE_MAP = {};

    for (var prop in Compiler.OPCODE_MAP) {
        var value = Compiler.OPCODE_MAP[prop];
        Compiler.DISASSEMBLE_MAP[value] = prop;
    }

    Compiler.multiParamSize = function (code) {
        return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];
    };

    Compiler.prototype = {
        compiler:Compiler,

        disassemble:function () {
            var opcodes = this.opcodes, opcode, nextCode;
            var out = [], str, name, value;

            for (var i = 0, l = opcodes.length; i < l; i++) {
                opcode = opcodes[i];

                if (opcode === 'DECLARE') {
                    name = opcodes[++i];
                    value = opcodes[++i];
                    out.push("DECLARE " + name + " = " + value);
                } else {
                    str = Compiler.DISASSEMBLE_MAP[opcode];

                    var extraParams = Compiler.multiParamSize(opcode);
                    var codes = [];

                    for (var j = 0; j < extraParams; j++) {
                        nextCode = opcodes[++i];

                        if (typeof nextCode === "string") {
                            nextCode = "\"" + nextCode.replace("\n", "\\n") + "\"";
                        }

                        codes.push(nextCode);
                    }

                    str = str + " " + codes.join(" ");

                    out.push(str);
                }
            }

            return out.join("\n");
        },

        guid:0,

        compile:function (program, options) {
            this.children = [];
            this.depths = {list:[]};
            this.options = options;

            // These changes will propagate to the other compiler components
            var knownHelpers = this.options.knownHelpers;
            this.options.knownHelpers = {
                'helperMissing':true,
                'blockHelperMissing':true,
                'each':true,
                'if':true,
                'unless':true,
                'with':true,
                'log':true
            };
            if (knownHelpers) {
                for (var name in knownHelpers) {
                    this.options.knownHelpers[name] = knownHelpers[name];
                }
            }

            return this.program(program);
        },

        accept:function (node) {
            return this[node.type](node);
        },

        program:function (program) {
            var statements = program.statements, statement;
            this.opcodes = [];

            for (var i = 0, l = statements.length; i < l; i++) {
                statement = statements[i];
                this[statement.type](statement);
            }
            this.isSimple = l === 1;

            this.depths.list = this.depths.list.sort(function (a, b) {
                return a - b;
            });

            return this;
        },

        compileProgram:function (program) {
            var result = new this.compiler().compile(program, this.options);
            var guid = this.guid++;

            this.usePartial = this.usePartial || result.usePartial;

            this.children[guid] = result;

            for (var i = 0, l = result.depths.list.length; i < l; i++) {
                depth = result.depths.list[i];

                if (depth < 2) {
                    continue;
                }
                else {
                    this.addDepth(depth - 1);
                }
            }

            return guid;
        },

        block:function (block) {
            var mustache = block.mustache;
            var depth, child, inverse, inverseGuid;

            var params = this.setupStackForMustache(mustache);

            var programGuid = this.compileProgram(block.program);

            if (block.program.inverse) {
                inverseGuid = this.compileProgram(block.program.inverse);
                this.declare('inverse', inverseGuid);
            }

            this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);
            this.declare('inverse', null);
            this.opcode('append');
        },

        inverse:function (block) {
            var params = this.setupStackForMustache(block.mustache);

            var programGuid = this.compileProgram(block.program);

            this.declare('inverse', programGuid);

            this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);
            this.declare('inverse', null);
            this.opcode('append');
        },

        hash:function (hash) {
            var pairs = hash.pairs, pair, val;

            this.opcode('push', '{}');

            for (var i = 0, l = pairs.length; i < l; i++) {
                pair = pairs[i];
                val = pair[1];

                this.accept(val);
                this.opcode('assignToHash', pair[0]);
            }
        },

        partial:function (partial) {
            var id = partial.id;
            this.usePartial = true;

            if (partial.context) {
                this.ID(partial.context);
            } else {
                this.opcode('push', 'depth0');
            }

            this.opcode('invokePartial', id.original);
            this.opcode('append');
        },

        content:function (content) {
            this.opcode('appendContent', content.string);
        },

        mustache:function (mustache) {
            var params = this.setupStackForMustache(mustache);

            this.opcode('invokeMustache', params.length, mustache.id.original, !!mustache.hash);

            if (mustache.escaped && !this.options.noEscape) {
                this.opcode('appendEscaped');
            } else {
                this.opcode('append');
            }
        },

        ID:function (id) {
            this.addDepth(id.depth);

            this.opcode('getContext', id.depth);

            this.opcode('lookupWithHelpers', id.parts[0] || null, id.isScoped || false);

            for (var i = 1, l = id.parts.length; i < l; i++) {
                this.opcode('lookup', id.parts[i]);
            }
        },

        STRING:function (string) {
            this.opcode('pushString', string.string);
        },

        INTEGER:function (integer) {
            this.opcode('push', integer.integer);
        },

        BOOLEAN:function (bool) {
            this.opcode('push', bool.bool);
        },

        comment:function () {
        },

        // HELPERS
        pushParams:function (params) {
            var i = params.length, param;

            while (i--) {
                param = params[i];

                if (this.options.stringParams) {
                    if (param.depth) {
                        this.addDepth(param.depth);
                    }

                    this.opcode('getContext', param.depth || 0);
                    this.opcode('pushStringParam', param.string);
                } else {
                    this[param.type](param);
                }
            }
        },

        opcode:function (name, val1, val2, val3) {
            this.opcodes.push(Compiler.OPCODE_MAP[name]);
            if (val1 !== undefined) {
                this.opcodes.push(val1);
            }
            if (val2 !== undefined) {
                this.opcodes.push(val2);
            }
            if (val3 !== undefined) {
                this.opcodes.push(val3);
            }
        },

        declare:function (name, value) {
            this.opcodes.push('DECLARE');
            this.opcodes.push(name);
            this.opcodes.push(value);
        },

        addDepth:function (depth) {
            if (depth === 0) {
                return;
            }

            if (!this.depths[depth]) {
                this.depths[depth] = true;
                this.depths.list.push(depth);
            }
        },

        setupStackForMustache:function (mustache) {
            var params = mustache.params;

            this.pushParams(params);

            if (mustache.hash) {
                this.hash(mustache.hash);
            }

            this.ID(mustache.id);

            return params;
        }
    };

    JavaScriptCompiler.prototype = {
        // PUBLIC API: You can override these methods in a subclass to provide
        // alternative compiled forms for name lookup and buffering semantics
        nameLookup:function (parent, name, type) {
            if (/^[0-9]+$/.test(name)) {
                return parent + "[" + name + "]";
            } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
                return parent + "." + name;
            }
            else {
                return parent + "['" + name + "']";
            }
        },

        appendToBuffer:function (string) {
            if (this.environment.isSimple) {
                return "return " + string + ";";
            } else {
                return "buffer += " + string + ";";
            }
        },

        initializeBuffer:function () {
            return this.quotedString("");
        },

        namespace:"Handlebars",
        // END PUBLIC API

        compile:function (environment, options, context, asObject) {
            this.environment = environment;
            this.options = options || {};

            this.name = this.environment.name;
            this.isChild = !!context;
            this.context = context || {
                programs:[],
                aliases:{ self:'this' },
                registers:{list:[]}
            };

            this.preamble();

            this.stackSlot = 0;
            this.stackVars = [];

            this.compileChildren(environment, options);

            var opcodes = environment.opcodes, opcode;

            this.i = 0;

            for (l = opcodes.length; this.i < l; this.i++) {
                opcode = this.nextOpcode(0);

                if (opcode[0] === 'DECLARE') {
                    this.i = this.i + 2;
                    this[opcode[1]] = opcode[2];
                } else {
                    this.i = this.i + opcode[1].length;
                    this[opcode[0]].apply(this, opcode[1]);
                }
            }

            return this.createFunctionContext(asObject);
        },

        nextOpcode:function (n) {
            var opcodes = this.environment.opcodes, opcode = opcodes[this.i + n], name, val;
            var extraParams, codes;

            if (opcode === 'DECLARE') {
                name = opcodes[this.i + 1];
                val = opcodes[this.i + 2];
                return ['DECLARE', name, val];
            } else {
                name = Compiler.DISASSEMBLE_MAP[opcode];

                extraParams = Compiler.multiParamSize(opcode);
                codes = [];

                for (var j = 0; j < extraParams; j++) {
                    codes.push(opcodes[this.i + j + 1 + n]);
                }

                return [name, codes];
            }
        },

        eat:function (opcode) {
            this.i = this.i + opcode.length;
        },

        preamble:function () {
            var out = [];

            // this register will disambiguate helper lookup from finding a function in
            // a context. This is necessary for mustache compatibility, which requires
            // that context functions in blocks are evaluated by blockHelperMissing, and
            // then proceed as if the resulting value was provided to blockHelperMissing.
            this.useRegister('foundHelper');

            if (!this.isChild) {
                var namespace = this.namespace;
                var copies = "helpers = helpers || " + namespace + ".helpers;";
                if (this.environment.usePartial) {
                    copies = copies + " partials = partials || " + namespace + ".partials;";
                }
                out.push(copies);
            } else {
                out.push('');
            }

            if (!this.environment.isSimple) {
                out.push(", buffer = " + this.initializeBuffer());
            } else {
                out.push("");
            }

            // track the last context pushed into place to allow skipping the
            // getContext opcode when it would be a noop
            this.lastContext = 0;
            this.source = out;
        },

        createFunctionContext:function (asObject) {
            var locals = this.stackVars;
            if (!this.isChild) {
                locals = locals.concat(this.context.registers.list);
            }

            if (locals.length > 0) {
                this.source[1] = this.source[1] + ", " + locals.join(", ");
            }

            // Generate minimizer alias mappings
            if (!this.isChild) {
                var aliases = []
                for (var alias in this.context.aliases) {
                    this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
                }
            }

            if (this.source[1]) {
                this.source[1] = "var " + this.source[1].substring(2) + ";";
            }

            // Merge children
            if (!this.isChild) {
                this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
            }

            if (!this.environment.isSimple) {
                this.source.push("return buffer;");
            }

            var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];

            for (var i = 0, l = this.environment.depths.list.length; i < l; i++) {
                params.push("depth" + this.environment.depths.list[i]);
            }

            if (asObject) {
                params.push(this.source.join("\n  "));

                return Function.apply(this, params);
            } else {
                var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n  ' + this.source.join("\n  ") + '}';
                Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
                return functionSource;
            }
        },

        appendContent:function (content) {
            this.source.push(this.appendToBuffer(this.quotedString(content)));
        },

        append:function () {
            var local = this.popStack();
            this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
            if (this.environment.isSimple) {
                this.source.push("else { " + this.appendToBuffer("''") + " }");
            }
        },

        appendEscaped:function () {
            var opcode = this.nextOpcode(1), extra = "";
            this.context.aliases.escapeExpression = 'this.escapeExpression';

            if (opcode[0] === 'appendContent') {
                extra = " + " + this.quotedString(opcode[1][0]);
                this.eat(opcode);
            }

            this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
        },

        getContext:function (depth) {
            if (this.lastContext !== depth) {
                this.lastContext = depth;
            }
        },

        lookupWithHelpers:function (name, isScoped) {
            if (name) {
                var topStack = this.nextStack();

                this.usingKnownHelper = false;

                var toPush;
                if (!isScoped && this.options.knownHelpers[name]) {
                    toPush = topStack + " = " + this.nameLookup('helpers', name, 'helper');
                    this.usingKnownHelper = true;
                } else if (isScoped || this.options.knownHelpersOnly) {
                    toPush = topStack + " = " + this.nameLookup('depth' + this.lastContext, name, 'context');
                } else {
                    this.register('foundHelper', this.nameLookup('helpers', name, 'helper'));
                    toPush = topStack + " = foundHelper || " + this.nameLookup('depth' + this.lastContext, name, 'context');
                }

                toPush += ';';
                this.source.push(toPush);
            } else {
                this.pushStack('depth' + this.lastContext);
            }
        },

        lookup:function (name) {
            var topStack = this.topStack();
            this.source.push(topStack + " = (" + topStack + " === null || " + topStack + " === undefined || " + topStack + " === false ? " +
                topStack + " : " + this.nameLookup(topStack, name, 'context') + ");");
        },

        pushStringParam:function (string) {
            this.pushStack('depth' + this.lastContext);
            this.pushString(string);
        },

        pushString:function (string) {
            this.pushStack(this.quotedString(string));
        },

        push:function (name) {
            this.pushStack(name);
        },

        invokeMustache:function (paramSize, original, hasHash) {
            this.populateParams(paramSize, this.quotedString(original), "{}", null, hasHash, function (nextStack, helperMissingString, id) {
                if (!this.usingKnownHelper) {
                    this.context.aliases.helperMissing = 'helpers.helperMissing';
                    this.context.aliases.undef = 'void 0';
                    this.source.push("else if(" + id + "=== undef) { " + nextStack + " = helperMissing.call(" + helperMissingString + "); }");
                    if (nextStack !== id) {
                        this.source.push("else { " + nextStack + " = " + id + "; }");
                    }
                }
            });
        },

        invokeProgram:function (guid, paramSize, hasHash) {
            var inverse = this.programExpression(this.inverse);
            var mainProgram = this.programExpression(guid);

            this.populateParams(paramSize, null, mainProgram, inverse, hasHash, function (nextStack, helperMissingString, id) {
                if (!this.usingKnownHelper) {
                    this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
                    this.source.push("else { " + nextStack + " = blockHelperMissing.call(" + helperMissingString + "); }");
                }
            });
        },

        populateParams:function (paramSize, helperId, program, inverse, hasHash, fn) {
            var needsRegister = hasHash || this.options.stringParams || inverse || this.options.data;
            var id = this.popStack(), nextStack;
            var params = [], param, stringParam, stringOptions;

            if (needsRegister) {
                this.register('tmp1', program);
                stringOptions = 'tmp1';
            } else {
                stringOptions = '{ hash: {} }';
            }

            if (needsRegister) {
                var hash = (hasHash ? this.popStack() : '{}');
                this.source.push('tmp1.hash = ' + hash + ';');
            }

            if (this.options.stringParams) {
                this.source.push('tmp1.contexts = [];');
            }

            for (var i = 0; i < paramSize; i++) {
                param = this.popStack();
                params.push(param);

                if (this.options.stringParams) {
                    this.source.push('tmp1.contexts.push(' + this.popStack() + ');');
                }
            }

            if (inverse) {
                this.source.push('tmp1.fn = tmp1;');
                this.source.push('tmp1.inverse = ' + inverse + ';');
            }

            if (this.options.data) {
                this.source.push('tmp1.data = data;');
            }

            params.push(stringOptions);

            this.populateCall(params, id, helperId || id, fn, program !== '{}');
        },

        populateCall:function (params, id, helperId, fn, program) {
            var paramString = ["depth0"].concat(params).join(", ");
            var helperMissingString = ["depth0"].concat(helperId).concat(params).join(", ");

            var nextStack = this.nextStack();

            if (this.usingKnownHelper) {
                this.source.push(nextStack + " = " + id + ".call(" + paramString + ");");
            } else {
                this.context.aliases.functionType = '"function"';
                var condition = program ? "foundHelper && " : ""
                this.source.push("if(" + condition + "typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }");
            }
            fn.call(this, nextStack, helperMissingString, id);
            this.usingKnownHelper = false;
        },

        invokePartial:function (context) {
            params = [this.nameLookup('partials', context, 'partial'), "'" + context + "'", this.popStack(), "helpers", "partials"];

            if (this.options.data) {
                params.push("data");
            }

            this.pushStack("self.invokePartial(" + params.join(", ") + ");");
        },

        assignToHash:function (key) {
            var value = this.popStack();
            var hash = this.topStack();

            this.source.push(hash + "['" + key + "'] = " + value + ";");
        },

        // HELPERS

        compiler:JavaScriptCompiler,

        compileChildren:function (environment, options) {
            var children = environment.children, child, compiler;

            for (var i = 0, l = children.length; i < l; i++) {
                child = children[i];
                compiler = new this.compiler();

                this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children
                var index = this.context.programs.length;
                child.index = index;
                child.name = 'program' + index;
                this.context.programs[index] = compiler.compile(child, options, this.context);
            }
        },

        programExpression:function (guid) {
            if (guid == null) {
                return "self.noop";
            }

            var child = this.environment.children[guid],
                depths = child.depths.list;
            var programParams = [child.index, child.name, "data"];

            for (var i = 0, l = depths.length; i < l; i++) {
                depth = depths[i];

                if (depth === 1) {
                    programParams.push("depth0");
                }
                else {
                    programParams.push("depth" + (depth - 1));
                }
            }

            if (depths.length === 0) {
                return "self.program(" + programParams.join(", ") + ")";
            } else {
                programParams.shift();
                return "self.programWithDepth(" + programParams.join(", ") + ")";
            }
        },

        register:function (name, val) {
            this.useRegister(name);
            this.source.push(name + " = " + val + ";");
        },

        useRegister:function (name) {
            if (!this.context.registers[name]) {
                this.context.registers[name] = true;
                this.context.registers.list.push(name);
            }
        },

        pushStack:function (item) {
            this.source.push(this.nextStack() + " = " + item + ";");
            return "stack" + this.stackSlot;
        },

        nextStack:function () {
            this.stackSlot++;
            if (this.stackSlot > this.stackVars.length) {
                this.stackVars.push("stack" + this.stackSlot);
            }
            return "stack" + this.stackSlot;
        },

        popStack:function () {
            return "stack" + this.stackSlot--;
        },

        topStack:function () {
            return "stack" + this.stackSlot;
        },

        quotedString:function (str) {
            return '"' + str
                .replace(/\\/g, '\\\\')
                .replace(/"/g, '\\"')
                .replace(/\n/g, '\\n')
                .replace(/\r/g, '\\r') + '"';
        }
    };

    var reservedWords = (
        "break else new var" +
            " case finally return void" +
            " catch for switch while" +
            " continue function this with" +
            " default if throw" +
            " delete in try" +
            " do instanceof typeof" +
            " abstract enum int short" +
            " boolean export interface static" +
            " byte extends long super" +
            " char final native synchronized" +
            " class float package throws" +
            " const goto private transient" +
            " debugger implements protected volatile" +
            " double import public let yield"
        ).split(" ");

    var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};

    for (var i = 0, l = reservedWords.length; i < l; i++) {
        compilerWords[reservedWords[i]] = true;
    }

    JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
        if (!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
            return true;
        }
        return false;
    }

})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);

Handlebars.precompile = function (string, options) {
    options = options || {};

    var ast = Handlebars.parse(string);
    var environment = new Handlebars.Compiler().compile(ast, options);
    return new Handlebars.JavaScriptCompiler().compile(environment, options);
};

Handlebars.compile = function (string, options) {
    options = options || {};

    var compiled;

    function compile() {
        var ast = Handlebars.parse(string);
        var environment = new Handlebars.Compiler().compile(ast, options);
        var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
        return Handlebars.template(templateSpec);
    }

    // Template is only compiled on first use and cached after that point.
    return function (context, options) {
        if (!compiled) {
            compiled = compile();
        }
        return compiled.call(this, context, options);
    };
};
;
// lib/handlebars/runtime.js
Handlebars.VM = {
    template:function (templateSpec) {
        // Just add water
        var container = {
            escapeExpression:Handlebars.Utils.escapeExpression,
            invokePartial:Handlebars.VM.invokePartial,
            programs:[],
            program:function (i, fn, data) {
                var programWrapper = this.programs[i];
                if (data) {
                    return Handlebars.VM.program(fn, data);
                } else if (programWrapper) {
                    return programWrapper;
                } else {
                    programWrapper = this.programs[i] = Handlebars.VM.program(fn);
                    return programWrapper;
                }
            },
            programWithDepth:Handlebars.VM.programWithDepth,
            noop:Handlebars.VM.noop
        };

        return function (context, options) {
            options = options || {};
            return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
        };
    },

    programWithDepth:function (fn, data, $depth) {
        var args = Array.prototype.slice.call(arguments, 2);

        return function (context, options) {
            options = options || {};

            return fn.apply(this, [context, options.data || data].concat(args));
        };
    },
    program:function (fn, data) {
        return function (context, options) {
            options = options || {};

            return fn(context, options.data || data);
        };
    },
    noop:function () {
        return "";
    },
    invokePartial:function (partial, name, context, helpers, partials, data) {
        options = { helpers:helpers, partials:partials, data:data };

        if (partial === undefined) {
            throw new Handlebars.Exception("The partial " + name + " could not be found");
        } else if (partial instanceof Function) {
            return partial(context, options);
        } else if (!Handlebars.compile) {
            throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
        } else {
            partials[name] = Handlebars.compile(partial);
            return partials[name](context, options);
        }
    }
};

Handlebars.template = Handlebars.VM.template;
;
